package io.hd;

import io.Archivo;
import io.servicios.Conexion;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Mariano Zapata
 */
public class GestorArchivo extends Thread {
    
    private GestorArchivoListener listener;
    private List<Archivo> archivosAbiertos;
    private final String directorioTemp;
    
    private static final int TAMANIO_BUFFER= 1024;
    private static final int TIEMPO_ESPERA= 3000;
    
    public GestorArchivo(String directorioTemp)
    {
        this.directorioTemp= directorioTemp;
        archivosAbiertos= new ArrayList<Archivo>();
        listener= null;
        this.controlarDirectorio();
    }
    
    @Override
    @SuppressWarnings("SleepWhileHoldingLock")
    public void run()
    {
        boolean vida= true;
        while (vida)
        {
            for (Archivo a : archivosAbiertos)
            {
                File fisico= new File(directorioTemp + a.getNombreFisico());
                if ((!a.isModificado()) && (a.getUltimaModificacion() != fisico.lastModified()))
                {
                    a.setModificado(true);
                    this.avisoArchivoModificado(a);
                }
            }
            try {
                Thread.sleep(TIEMPO_ESPERA);
            } catch (InterruptedException ex) {vida= false;}
        }
    }
    
    public void detener() {
        this.interrupt();
    }
    
    public void escribirArchivoEnServidor(File archivo, Conexion conexion, String nombreArchivoTempServidor)
            throws FileNotFoundException, IOException
    {
        FileInputStream lector= new FileInputStream(archivo);
        byte [] buffer= new byte[TAMANIO_BUFFER];
        int n;
        while ((n= lector.read(buffer)) != -1)
            conexion.getServiciosServidor().escribirArchivoTemporal(nombreArchivoTempServidor, buffer, n);
        lector.close();
    }
    
    public void abrirArchivo(Archivo archivo, String pathAplicacion) throws IOException
    {
        String pathArchivo= directorioTemp + archivo.getNombreFisico();
        File fisico= new File(pathArchivo);
        archivo.setUltimaModificacion(fisico.lastModified());
        Runtime ejecutor= Runtime.getRuntime();
        String comando= pathAplicacion + " " + pathArchivo;
        archivosAbiertos.add(archivo);
        ejecutor.exec(comando);
    }
    
    public boolean cerrarArchivo(Archivo a, boolean guardar, Conexion con, String nombreArchivoTempServidor)
            throws FileNotFoundException, IOException
    {
        Archivo archivoAbierto= this.getArchivoAbierto(a.obtenerId());
        File f= new File(directorioTemp + archivoAbierto.getNombreFisico());
        if (guardar)
        {
            this.escribirArchivoEnServidor(f, con, nombreArchivoTempServidor);
            archivoAbierto.setUltimaModificacion(f.lastModified());
            archivoAbierto.setModificado(false);
        }
        if (f.delete())
        {
            archivosAbiertos.remove(archivoAbierto);
            return true;
        }
        else
            return false;
    }
    
    private Archivo getArchivoAbierto(long id)
    {
        for (Archivo a : archivosAbiertos)
        {
            if (a.obtenerId() == id)
                return a;
        }
        return null;
    }
    
    public boolean estaAbierto(Archivo a) {
        return archivosAbiertos.contains(a);
    }
    
    public boolean hayArchivosAbiertos() {
        return !archivosAbiertos.isEmpty();
    }
    
    private void controlarDirectorio()
    {
        File dir= new File(directorioTemp);
        File [] archs= dir.listFiles();
        for (File f : archs)
            f.delete();
    }
    
    public void agregarGestorArchivoListener(GestorArchivoListener gal) {
        listener= gal;
    }
    
    public void quitarGestorArchivoListener() {
        listener= null;
    }
    
    private void avisoArchivoModificado(Archivo mod)
    {
        if (listener != null)
            listener.archivoModificado(mod);
    }
}